package com.lp.biz.content.service.impl;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.lp.biz.category.mapper.BizCategoryLabelMapper;
import com.lp.biz.category.mapper.BizCategoryMapper;
import com.lp.biz.category.model.entity.BizCategory;
import com.lp.biz.category.model.entity.BizCategoryLabel;
import com.lp.biz.content.mapper.BizContentScheduleMapper;
import com.lp.biz.content.mapper.BizCourseChapterMapper;
import com.lp.biz.content.model.entity.BizContentSchedule;
import com.lp.biz.content.model.entity.BizCoreContent;
import com.lp.biz.content.mapper.BizCoreContentMapper;
import com.lp.biz.content.model.entity.BizCourseChapter;
import com.lp.biz.content.model.query.CourseQuery;
import com.lp.biz.content.model.query.FamousQuery;
import com.lp.biz.content.model.query.ReadingQuery;
import com.lp.biz.content.model.query.StoryQuery;
import com.lp.biz.content.model.vo.*;
import com.lp.biz.content.service.BizCoreContentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lp.biz.operations.mapper.BizRecommendDailyMapper;
import com.lp.biz.operations.model.entity.BizRecommendDaily;
import com.lp.common.component.RedisService;
import com.lp.common.entity.PageParams;
import com.lp.common.exception.BaseException;
import com.lp.common.exception.ErrorCodeEnum;
import com.lp.common.utils.CommonResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import static com.lp.common.constant.CacheConstant.BIZ_HOME_KEY;
import static com.lp.common.constant.CategoryConstant.*;
import static com.lp.common.constant.CommonConstant.NEGATE;
import static com.lp.common.constant.CommonConstant.SURE;
import static com.lp.common.constant.HomeConstant.CODE_DAILY;
import static com.lp.common.utils.Tools.copyPage;

/**
 * @program: backend
 * @description: BizCoreContent 服务实现类
 * @author Ke.Song
 * @since 2024-05-31 23:14:47
 */
@Service
public class BizCoreContentServiceImpl extends ServiceImpl<BizCoreContentMapper, BizCoreContent> implements BizCoreContentService {

    @Autowired
    private RedisService redis;

    @Autowired
    private BizCategoryMapper categoryMapper;

    @Autowired
    private BizCoreContentMapper contentMapper;

    @Autowired
    private BizCategoryLabelMapper labelMapper;

    @Autowired
    private BizRecommendDailyMapper dailyMapper;

    @Autowired
    private BizCourseChapterMapper chapterMapper;

    @Autowired
    private BizContentScheduleMapper scheduleMapper;

    @Override
    public CommonResult getReadingList(ReadingQuery query) {
        PageHelper.startPage(query.getPage(), query.getSize());
        return CommonResult.restPage(contentMapper.getReadingList(query));
    }

    /**
     * 增加或更新阅读内容。
     * @param reading 阅读内容的信息。
     * @throws BaseException 如果操作失败或参数不正确。
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void addOrUpdateReading(Reading reading) {
        // 检查是否有相同标题的阅读内容已存在
        BizCoreContent exitsContent = contentMapper.selectOne(new QueryWrapper<BizCoreContent>().lambda()
                .eq(BizCoreContent::getTitle, reading.getTitle()).eq(BizCoreContent::getBizCategoryCode, CODE_READING)
                .eq(BizCoreContent::getIsDeleted, NEGATE));
        // 验证显示类型是否有效
        if (!reading.getDisplayType().equals(DISPLAY_TYPE_NOW) && !reading.getDisplayType().equals(DISPLAY_TYPE_TIME)
                && !reading.getDisplayType().equals(DISPLAY_TYPE_NOT)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        // 根据类别代码获取阅读类别
        BizCategory category = checkLabelAndGetCategory(CODE_READING, reading.getLabelId());
        BizCoreContent content;
        // 如果阅读内容ID为空，表示是新增内容
        if (reading.getId() == null) {
            // 如果已存在相同标题的内容，抛出异常
            if (exitsContent != null) {
                throw new BaseException(ErrorCodeEnum.DUPLICATE_DATA);
            }
            // 生成阅读内容实体
            content = generateReading(reading);
            // 设置类别ID和类别代码
            content.setBizCategoryId(category.getId());
            content.setBizCategoryCode(category.getCode());
            // 插入新的阅读内容
            contentMapper.insert(content);
        } else {
            // 如果阅读内容ID不为空，表示是更新内容
            content = checkBizCoreContent(reading.getId(), exitsContent);
            // 校验并更新阅读内容的显示状态
            LocalDateTime now = LocalDateTime.now();
            checkDisplay(content, reading);
            // 更新数据库中的内容信息
            contentMapper.update(null, new UpdateWrapper<BizCoreContent>().lambda()
                    .eq(BizCoreContent::getId, reading.getId())
                    .set(BizCoreContent::getId, reading.getId())
                    .set(BizCoreContent::getTitle, reading.getTitle())
                    .set(BizCoreContent::getImageV, reading.getImage())
                    .set(BizCoreContent::getBizLabelId, reading.getLabelId())
                    .set(BizCoreContent::getDescription, reading.getDescription())
                    .set(BizCoreContent::getAudioUrl, reading.getAudioUrl())
                    .set(BizCoreContent::getSort, reading.getSort())
                    .set(BizCoreContent::getContent, reading.getContent())
                    .set(BizCoreContent::getProfile, reading.getProfile())
                    .set(BizCoreContent::getIsDisplay, content.getIsDisplay())
                    .set(BizCoreContent::getDisplayAt, content.getDisplayAt())
                    .set(BizCoreContent::getDuration, reading.getDuration())
                    .set(BizCoreContent::getUpdateAt, now));
        }
        // 删除与内容关联的发布计划
        scheduleMapper.delete(new QueryWrapper<BizContentSchedule>().lambda()
                .eq(      BizContentSchedule::getContentId, content.getId())
                .eq(BizContentSchedule::getCode, content.getBizCategoryCode()));
        // 如果显示类型为定时，创建新的发布计划
        if (reading.getDisplayType().equals(DISPLAY_TYPE_TIME)) {
            BizContentSchedule schedule = new BizContentSchedule();
            schedule.setContentId(content.getId());
            schedule.setCode(content.getBizCategoryCode());
            schedule.setStartAt(reading.getDisplayAt());
            schedule.setStatus(content.getIsDisplay());
            scheduleMapper.insert(schedule);
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void readingDisplay(Integer readingId) {
        BizCoreContent content = contentMapper.selectById(readingId);
        if (content == null || !content.getBizCategoryCode().equals(CODE_READING) || content.getIsDeleted().equals(SURE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        contentMapper.update(null, new UpdateWrapper<BizCoreContent>().lambda()
                .eq(BizCoreContent::getId, readingId)
                .set(BizCoreContent::getIsDisplay, content.getIsDisplay().equals(NEGATE) ? SURE :NEGATE)
                .set(BizCoreContent::getDisplayAt, content.getIsDisplay().equals(NEGATE) ? LocalDateTime.now() : null));
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void deleteReading(Integer readingId) {
        BizCoreContent content = contentMapper.selectById(readingId);
        if (content == null || !content.getBizCategoryCode().equals(CODE_READING) || content.getIsDeleted().equals(SURE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        contentMapper.update(null, new UpdateWrapper<BizCoreContent>().lambda()
                .eq(BizCoreContent::getId, readingId)
                .set(BizCoreContent::getIsDeleted, SURE));
        // 删除与内容关联的发布计划
        scheduleMapper.delete(new QueryWrapper<BizContentSchedule>().lambda()
                .eq(BizContentSchedule::getContentId, content.getId())
                .eq(BizContentSchedule::getCode, content.getBizCategoryCode()));
    }

    @Override
    public CommonResult getReading(Integer readingId) {
        BizCoreContent content = contentMapper.selectById(readingId);
        if (content == null || !content.getBizCategoryCode().equals(CODE_READING) || content.getIsDeleted().equals(SURE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        Reading reading = new Reading();
        reading.setId(content.getId());
        reading.setTitle(content.getTitle());
        reading.setImage(content.getImageV());
        reading.setDescription(content.getDescription());
        reading.setAudioUrl(content.getAudioUrl());
        reading.setSort(content.getSort());
        reading.setProfile(content.getProfile());
        reading.setDisplayType(content.getDisplayType());
        reading.setContent(content.getContent());
        reading.setDuration(content.getDuration());
        if (content.getBizLabelId() != null) {
            BizCategoryLabel label = labelMapper.selectById(content.getBizLabelId());
            if (label != null) {
                reading.setLabelId(content.getBizLabelId());
                reading.setLabel(label.getName());
            }
        }
        if (content.getDisplayType().equals(DISPLAY_TYPE_TIME)) {
            BizContentSchedule schedule = scheduleMapper.selectOne(new QueryWrapper<BizContentSchedule>().lambda()
                    .eq(BizContentSchedule::getContentId, content.getId())
                    .eq(BizContentSchedule::getCode, content.getBizCategoryCode()));
            if (schedule != null) {
                reading.setDisplayAt(reading.getDisplayAt() == null ? schedule.getStartAt() : reading.getDisplayAt());
            }
        }
        return CommonResult.success(reading);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void addOrUpdateFamous(Famous famous) {
        BizCategory category = categoryMapper.selectOne(new QueryWrapper<BizCategory>().lambda()
                .eq(BizCategory::getCode, CODE_FAMOUS_REMARK));
        if (famous.getLabelId() != null) {
            BizCategoryLabel label = labelMapper.selectById(famous.getLabelId());
            if (label == null || !label.getBizCategoryId().equals(category.getId())) {
                throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
            }
        }
        if (famous.getIsDisplay() != null) {
            if (!famous.getIsDisplay().equals(NEGATE) && !famous.getIsDisplay().equals(SURE)) {
                throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
            }
        } else {
            famous.setIsDisplay(NEGATE);
        }
        BizCoreContent exits = contentMapper.selectOne(new QueryWrapper<BizCoreContent>().lambda()
                .eq(BizCoreContent::getContent, famous.getContent().trim()).eq(BizCoreContent::getIsDeleted, NEGATE));
        if (famous.getId() == null && exits == null) {
            BizCoreContent content = new BizCoreContent();
            content.setContent(famous.getContent());
            content.setBizLabelId(famous.getLabelId());
            content.setIsDisplay(famous.getIsDisplay());
            content.setSort(famous.getSort());
            content.setBizCategoryCode(category.getCode());
            content.setBizCategoryId(category.getId());
            content.setAuthor(famous.getAuthor());
            if (famous.getIsDisplay().equals(SURE)) {
                content.setDisplayAt(LocalDateTime.now());
            }
            contentMapper.insert(content);
        } else if (famous.getId() != null && (exits == null || exits.getId().equals(famous.getId()))) {
            BizCoreContent content = contentMapper.selectById(famous.getId());
            if (content == null || content.getIsDeleted().equals(SURE) || !content.getBizCategoryId().equals(category.getId())) {
                throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
            }
            LambdaUpdateWrapper<BizCoreContent> updateWrapper = new UpdateWrapper<BizCoreContent>().lambda()
                    .eq(BizCoreContent::getId, famous.getId())
                    .set(BizCoreContent::getContent, famous.getContent())
                    .set(BizCoreContent::getBizLabelId, famous.getLabelId())
                    .set(BizCoreContent::getIsDisplay, famous.getIsDisplay())
                    .set(BizCoreContent::getUpdateAt, LocalDateTime.now())
                    .set(BizCoreContent::getSort, famous.getSort());
            if (famous.getIsDisplay().equals(SURE) && content.getDisplayAt() == null) {
                updateWrapper.set(BizCoreContent::getDisplayAt, LocalDateTime.now());
            } else if (famous.getIsDisplay().equals(NEGATE)) {
                updateWrapper.set(BizCoreContent::getDisplayAt, null);
            }
            contentMapper.update(null, updateWrapper);
        } else {
            throw new BaseException("内容已存在");
        }
    }

    @Override
    public CommonResult getFamous(Integer famousId) {
        BizCoreContent content = contentMapper.selectById(famousId);
        if (content == null || content.getIsDeleted().equals(SURE) || !content.getBizCategoryCode().equals(CODE_FAMOUS_REMARK)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        Famous famous = new Famous();
        famous.setId(content.getId());
        famous.setContent(content.getContent());
        famous.setIsDisplay(content.getIsDisplay());
        famous.setSort(content.getSort());
        if (content.getBizLabelId() != null) {
            BizCategoryLabel label = labelMapper.selectById(content.getBizLabelId());
            famous.setLabelId(content.getBizLabelId());
            famous.setLabel(label.getName());
        }
        return CommonResult.success(famous);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void deleteFamous(Integer famousId) {
        BizCoreContent content = contentMapper.selectById(famousId);
        if (content == null || !content.getBizCategoryCode().equals(CODE_FAMOUS_REMARK)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        update(new UpdateWrapper<BizCoreContent>().lambda().eq(BizCoreContent::getId, famousId)
                .set(BizCoreContent::getIsDeleted, SURE));
    }

    @Override
    public CommonResult getFamousList(FamousQuery query) {
        PageHelper.startPage(query.getPage(), query.getSize());
        return CommonResult.restPage(contentMapper.getFamousList(query));
    }

    @Override
    public CommonResult getStories(StoryQuery query) {
        PageHelper.startPage(query.getPage(), query.getSize());
        if (query.getStatus() != null && !query.getStatus().equals(NEGATE) && !query.getStatus().equals(SURE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }

        query.setTitle(query.getTitle() == null || StringUtils.isBlank(query.getTitle()) ? null : query.getTitle());
        query.setDisplayAt(query.getDisplayAt() == null || StringUtils.isBlank(query.getDisplayAt()) ? null : query.getDisplayAt());
        List<StoryList> storyList = contentMapper.getStories(query);
        return CommonResult.restPage(storyList);
    }

    private void generateStoryList(Page<StoryList> storyList, Integer id, String title, String content,
                                   Integer isDisplay, LocalDateTime displayAt, String image) {
        StoryList story = new StoryList();
        story.setId(id);
        story.setTitle(title);
        story.setContent(content);
        story.setStatus(isDisplay);
        story.setDisplayAt(displayAt);
        story.setImage(image);
        storyList.add(story);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void displayStory(Integer storyId) {
        BizCoreContent story = contentMapper.selectById(storyId);
        if (story == null || story.getIsDeleted().equals(SURE) ||!story.getBizCategoryCode().equals(CODE_STORY)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        if (story.getIsDisplay() == null || story.getIsDisplay().equals(NEGATE)) {
            contentMapper.update(null, new UpdateWrapper<BizCoreContent>().lambda()
                    .eq(BizCoreContent::getId, storyId)
                    .set(BizCoreContent::getIsDisplay, SURE)
                    .set(BizCoreContent::getDisplayAt, LocalDateTime.now()));
        } else {
            contentMapper.update(null, new UpdateWrapper<BizCoreContent>().lambda()
                    .eq(BizCoreContent::getId, storyId)
                    .set(BizCoreContent::getIsDisplay, NEGATE)
                    .set(BizCoreContent::getDisplayAt, null));
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void deleteStory(Integer storyId) {
        BizCoreContent story = contentMapper.selectById(storyId);
        if (story == null || !story.getBizCategoryCode().equals(CODE_STORY)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        if (story.getIsDeleted().equals(NEGATE)) {
            contentMapper.update(null, new UpdateWrapper<BizCoreContent>().lambda()
                    .eq(BizCoreContent::getId, storyId)
                    .set(BizCoreContent::getIsDeleted, SURE));
        }
    }

    @Override
    public CommonResult getStory(Integer storyId) {
        BizCoreContent content = contentMapper.selectById(storyId);
        if (content == null || !content.getBizCategoryCode().equals(CODE_STORY)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        Story story = new Story();
        story.setId(content.getId());
        story.setTitle(content.getTitle());
        story.setImage(content.getImageV());
        story.setAudioUrl(content.getAudioUrl());
        story.setProfile(content.getProfile());
        story.setContent(content.getContent());
        story.setSort(content.getSort());
        story.setIsDisplay(content.getIsDisplay());
        story.setDuration(content.getDuration());
        story.setImage(content.getImageV());
        if (content.getBizLabelId() != null) {
            BizCategoryLabel label = labelMapper.selectById(content.getBizLabelId());
            if (label != null) {
                story.setLabelId(label.getId());
                story.setLabel(label.getName());
            }
        }
        return CommonResult.success(story);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void addOrUpdateStory(Story story) {
        BizCoreContent content;
        BizCoreContent exitsStory = contentMapper.selectOne(new QueryWrapper<BizCoreContent>().lambda()
                .eq(BizCoreContent::getTitle, story.getTitle()).eq(BizCoreContent::getBizCategoryCode, CODE_STORY)
                .eq(BizCoreContent::getIsDeleted, NEGATE));
        if (story.getIsDisplay() == null) {
            story.setIsDisplay(NEGATE);
        } else if (!story.getIsDisplay().equals(NEGATE) && !story.getIsDisplay().equals(SURE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        if (story.getId() == null) {
            if (exitsStory != null) {
                throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
            }
            BizCategory category = checkLabelAndGetCategory(CODE_STORY, story.getLabelId());
            content = new BizCoreContent();
            content.setBizCategoryId(category.getId());
            content.setBizCategoryCode(category.getCode());
            content.setBizLabelId(story.getLabelId());
            content.setTitle(story.getTitle());
            content.setContent(story.getContent());
            content.setImageV(story.getImage());
            content.setAudioUrl(story.getAudioUrl());
            content.setIsDisplay(story.getIsDisplay());
            content.setDisplayAt(story.getIsDisplay().equals(NEGATE) ? null : LocalDateTime.now());
            content.setDuration(story.getDuration());
            content.setCreateAt(LocalDateTime.now());
            content.setProfile(story.getProfile());
            content.setSort(story.getSort());
            contentMapper.insert(content);
        } else {
            checkBizCoreContent(story.getId(), exitsStory);
            contentMapper.update(null, new UpdateWrapper<BizCoreContent>().lambda()
                    .eq(BizCoreContent::getId, story.getId())
                    .set(BizCoreContent::getBizLabelId, story.getLabelId())
                    .set(BizCoreContent::getTitle, story.getTitle())
                    .set(BizCoreContent::getContent, story.getContent())
                    .set(BizCoreContent::getImageV, story.getImage())
                    .set(BizCoreContent::getAudioUrl, story.getAudioUrl())
                    .set(BizCoreContent::getIsDisplay, story.getIsDisplay())
                    .set(BizCoreContent::getDisplayAt, story.getIsDisplay().equals(NEGATE) ? null : LocalDateTime.now())
                    .set(BizCoreContent::getDuration, story.getDuration())
                    .set(BizCoreContent::getCreateAt, LocalDateTime.now())
                    .set(BizCoreContent::getProfile, story.getProfile())
                    .set(BizCoreContent::getSort, story.getSort()));
        }
    }

    @Override
    public CommonResult getDailyStoryList(StoryQuery query) {
        LambdaQueryWrapper<BizRecommendDaily> queryWrapper = new QueryWrapper<BizRecommendDaily>().lambda()
                .eq(BizRecommendDaily::getIsDeleted, NEGATE);
        if (query.getTitle() != null) {
            queryWrapper.like(BizRecommendDaily::getTitle, query.getTitle());
        }
        if (query.getDisplayAt() != null) {
            queryWrapper.likeLeft(BizRecommendDaily::getDisplayAt, query.getDisplayAt());
        }
        if (query.getStatus() != null) {
            if (query.getStatus().equals(NEGATE) || query.getStatus().equals(SURE)) {
                queryWrapper.like(BizRecommendDaily::getIsDisplay, query.getStatus());
            } else {
                throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
            }
        }
        queryWrapper.orderByDesc(BizRecommendDaily::getCreateAt);
        PageHelper.startPage(query.getPage(), query.getSize());
        List<BizRecommendDaily> bizRecommendDailies = dailyMapper.selectList(queryWrapper);
        Page<StoryList> storyLists = copyPage(new Page<>(), bizRecommendDailies);
        for (BizRecommendDaily daily : bizRecommendDailies) {
            generateStoryList(storyLists, daily.getId(), daily.getTitle(), daily.getContent(), daily.getIsDisplay(),
                    daily.getDisplayAt(), daily.getImageV());
        }
        return CommonResult.restPage(storyLists);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void deleteDailyStory(Integer storyId) {
        BizRecommendDaily daily = dailyMapper.selectById(storyId);
        if (daily == null) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        if (daily.getIsDeleted().equals(NEGATE)) {
            daily.setIsDeleted(SURE);
            dailyMapper.updateById(daily);
        }
        redis.delete(BIZ_HOME_KEY);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void dailyStoryDisplay(Integer storyId) {
        BizRecommendDaily daily = dailyMapper.selectById(storyId);
        if (daily == null || daily.getIsDeleted().equals(SURE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        if (daily.getIsDisplay() == null || daily.getIsDisplay().equals(NEGATE)) {
            dailyMapper.update(null, new UpdateWrapper<BizRecommendDaily>()
                    .lambda()
                    .eq(BizRecommendDaily::getId, storyId)
                    .set(BizRecommendDaily::getIsDisplay, SURE)
                    .set(BizRecommendDaily::getDisplayAt, LocalDateTime.now()));
        } else {
            dailyMapper.update(null, new UpdateWrapper<BizRecommendDaily>()
                    .lambda()
                    .eq(BizRecommendDaily::getId, storyId)
                    .set(BizRecommendDaily::getIsDisplay, NEGATE)
                    .set(BizRecommendDaily::getDisplayAt, null));
        }
        redis.delete(BIZ_HOME_KEY);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void addOrUpdateDailyStory(Daily daily) {
        // 校验每日故事的显示类型是否合法
        if (!daily.getDisplayType().equals(DISPLAY_TYPE_NOW) && !daily.getDisplayType().equals(DISPLAY_TYPE_TIME)
                && !daily.getDisplayType().equals(DISPLAY_TYPE_NOT)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        // 查询是否存在相同标题且未被删除的每日故事
        BizRecommendDaily exitsDail = dailyMapper.selectOne(new QueryWrapper<BizRecommendDaily>().lambda()
                .eq(BizRecommendDaily::getTitle, daily.getTitle()).eq(BizRecommendDaily::getIsDeleted, NEGATE));

        BizRecommendDaily dailyStory;
        // 如果每日故事ID为空，则创建新记录；否则更新现有记录
        if (daily.getId() == null) {
            // 如果已存在相同标题的每日故事，则抛出异常
            if (exitsDail != null) {
                throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
            }
            dailyStory = new BizRecommendDaily();
            // 设置新每日故事的属性
            dailyStory.setTitle(daily.getTitle());
            dailyStory.setContent(daily.getContent());
            dailyStory.setAudioUrl(daily.getAudioUrl());
            dailyStory.setDuration(daily.getDuration());
            dailyStory.setCreateAt(LocalDateTime.now());
            dailyStory.setProfile(daily.getProfile());
            dailyStory.setIsDeleted(NEGATE);
            dailyStory.setSort(daily.getSort());
            dailyStory.setImageV(daily.getImage());
            checkDisplay(dailyStory, daily);
            dailyMapper.insert(dailyStory);
        } else {
            dailyStory = dailyMapper.selectById(daily.getId());
            // 如果每日故事ID不存在或已被删除，则抛出异常
            if (dailyStory == null || dailyStory.getIsDeleted().equals(SURE)) {
                throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
            } else if (exitsDail != null && !exitsDail.getId().equals(dailyStory.getId())) {
                throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
            }
            checkDisplay(dailyStory, daily);
            // 更新每日故事的信息
            dailyMapper.update(null, new UpdateWrapper<BizRecommendDaily>().lambda()
                    .eq(BizRecommendDaily::getId, daily.getId())
                    .set(BizRecommendDaily::getTitle, daily.getTitle())
                    .set(BizRecommendDaily::getContent, daily.getContent())
                    .set(BizRecommendDaily::getAudioUrl, daily.getAudioUrl())
                    .set(BizRecommendDaily::getDuration, daily.getDuration())
                    .set(BizRecommendDaily::getIsDisplay, dailyStory.getIsDisplay())
                    .set(BizRecommendDaily::getDisplayType, dailyStory.getDisplayType())
                    .set(BizRecommendDaily::getDisplayAt, dailyStory.getDisplayAt())
                    .set(BizRecommendDaily::getSort, daily.getSort())
                    .set(BizRecommendDaily::getImageV, daily.getImage())
                    .set(BizRecommendDaily::getProfile, daily.getProfile()));
        }

        // 删除与每日故事关联的调度信息
        scheduleMapper.delete(new QueryWrapper<BizContentSchedule>().lambda()
                .eq(BizContentSchedule::getContentId, dailyStory.getId())
                .eq(BizContentSchedule::getCode, CODE_DAILY));

        // 如果每日故事的显示类型为定时，则创建新的调度信息
        if (dailyStory.getDisplayType().equals(DISPLAY_TYPE_TIME)) {
            BizContentSchedule schedule = new BizContentSchedule();
            schedule.setContentId(dailyStory.getId());
            schedule.setCode(CODE_DAILY);
            schedule.setStartAt(daily.getDisplayAt());
            schedule.setStatus(dailyStory.getIsDisplay());
            scheduleMapper.insert(schedule);
        }
        redis.delete(BIZ_HOME_KEY);
    }

    @Override
    public CommonResult getDailyStory(Integer dailyId) {
        BizRecommendDaily dailyStory = dailyMapper.selectById(dailyId);
        if (dailyStory == null || dailyStory.getIsDeleted().equals(SURE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        Daily daily = new Daily();
        daily.setId(dailyStory.getId());
        daily.setTitle(dailyStory.getTitle());
        daily.setAudioUrl(dailyStory.getAudioUrl());
        daily.setProfile(dailyStory.getProfile());
        daily.setContent(dailyStory.getContent());
        daily.setSort(dailyStory.getSort());
        daily.setDuration(dailyStory.getDuration());
        daily.setDisplayType(dailyStory.getDisplayType());
        daily.setDisplayAt(dailyStory.getDisplayAt());
        daily.setImage(dailyStory.getImageV());
        if (dailyStory.getDisplayType().equals(DISPLAY_TYPE_TIME)) {
            BizContentSchedule schedule = scheduleMapper.selectOne(new QueryWrapper<BizContentSchedule>().lambda()
                    .eq(BizContentSchedule::getContentId, dailyId).eq(BizContentSchedule::getCode, CODE_DAILY));
            if (schedule != null) {
                daily.setDisplayAt(schedule.getStartAt());
            }
        }
        return CommonResult.success(daily);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void addOrUpdateCourse(Course params) {
        BizCategory category = checkLabelAndGetCategory(CODE_COURSE, params.getLabelId());
        BizCoreContent exist = contentMapper.selectOne(new QueryWrapper<BizCoreContent>().lambda()
                .eq(BizCoreContent::getTitle, params.getTitle())
                .eq(BizCoreContent::getBizCategoryCode, CODE_COURSE).eq(BizCoreContent::getIsDeleted, NEGATE));
        BizCoreContent course = generateCourse(params, category);
        if (params.getId() == null && exist == null) {
            contentMapper.insert(course);
        } else if (params.getId() != null) {
            if (exist != null && !params.getId().equals(exist.getId())) {
                throw new BaseException("标题输入错误");
            }
            BizCoreContent content = contentMapper.selectById(params.getId());
            if (content == null || content.getIsDeleted().equals(SURE) || !content.getBizCategoryCode().equals(CODE_COURSE)) {
                throw new BaseException("课程输入错误");
            }
            contentMapper.update(null, new UpdateWrapper<BizCoreContent>().lambda()
                    .eq(BizCoreContent::getId, params.getId())
                    .set(BizCoreContent::getTitle, course.getTitle())
                    .set(BizCoreContent::getDescription, course.getDescription())
                    .set(BizCoreContent::getBizLabelId, course.getBizLabelId())
                    .set(BizCoreContent::getNum, course.getNum())
                    .set(BizCoreContent::getImageT, course.getImageT())
                    .set(BizCoreContent::getImageV, course.getImageV())
                    .set(BizCoreContent::getIsCharge, course.getIsCharge())
                    .set(BizCoreContent::getIsDisplay, course.getIsDisplay())
                    .set(BizCoreContent::getProfile, course.getProfile())
                    .set(BizCoreContent::getOriginalPrice, course.getOriginalPrice())
                    .set(BizCoreContent::getActualPrice, course.getActualPrice())
                    .set(BizCoreContent::getBizCategoryId, course.getBizCategoryId())
                    .set(BizCoreContent::getBizCategoryCode, course.getBizCategoryCode())
                    .set(BizCoreContent::getDisplayAt, course.getDisplayAt())
                    .set(BizCoreContent::getCreateAt, course.getCreateAt())
                    .set(BizCoreContent::getUpdateAt, course.getUpdateAt())
                    .set(BizCoreContent::getSort, course.getSort())
                    .set(BizCoreContent::getDisplayAt, course.getDisplayAt()));
        } else {
            throw new BaseException("标题输入错误");
        }

    }

    @Override
    public CommonResult getCourses(CourseQuery query) {
        if (query.getStatus() != null) {
            if (!query.getStatus().equals(NEGATE) && !query.getStatus().equals(SURE)) {
                throw new BaseException("状态输入错误");
            }
        }
        query.setTitle(StringUtils.isNotBlank(query.getTitle()) ? query.getTitle().trim() : null);
        PageHelper.startPage(query.getPage(), query.getSize());
        return CommonResult.restPage(baseMapper.getCourses(query));
    }

    @Override
    public CommonResult getCourseDetail(Integer courseId) {
        BizCoreContent content = getById(courseId);
        if (content == null || content.getIsDeleted().equals(SURE) || !content.getBizCategoryCode().equals(CODE_COURSE)) {
            throw new BaseException("课程输入错误");
        }
        Course course = new Course();
        course.setId(content.getId());
        course.setTitle(content.getTitle());
        course.setDescription(content.getDescription());
        course.setNum(content.getNum());
        course.setImageT(content.getImageT());
        course.setImageV(content.getImageV());
        course.setIsCharge(content.getIsCharge());
        course.setIsDisplay(content.getIsDisplay());
        course.setProfile(content.getProfile());
        course.setActualPrice(content.getActualPrice());
        course.setOriginalPrice(content.getOriginalPrice());
        course.setSort(content.getSort());
        if (content.getBizLabelId() != null) {
            BizCategoryLabel label = labelMapper.selectById(content.getBizLabelId());
            course.setLabelId(label.getId());
            course.setLabel(label.getName());
        }
        return CommonResult.success(course);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void deleteCourse(Integer courseId) {
        BizCoreContent course = getById(courseId);
        if (course == null || course.getIsDeleted().equals(SURE)) {
            throw new BaseException("课程输入错误");
        }
        course.setIsDeleted(SURE);
        updateById(course);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void updateCourseStatus(Integer courseId) {
        BizCoreContent content = getById(courseId);
        if (content == null || content.getIsDeleted().equals(SURE) || !content.getBizCategoryCode().equals(CODE_COURSE)) {
            throw new BaseException("课程输入错误");
        }
        update(null, new UpdateWrapper<BizCoreContent>().lambda()
                .eq(BizCoreContent::getId, courseId)
                .set(BizCoreContent::getIsDisplay, content.getIsDisplay().equals(NEGATE) ? SURE : NEGATE)
                .set(BizCoreContent::getDisplayAt, content.getIsDisplay().equals(NEGATE) ? LocalDateTime.now() : null));
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void addOrUpdateChapter(Integer courseId, Chapter chapter) {
        BizCoreContent course = getById(courseId);
        if (course == null || course.getIsDeleted().equals(SURE)) {
            throw new BaseException("课程输入错误");
        } else if (chapter.getArrange() != null && !chapter.getArrange().equals(1) && !chapter.getArrange().equals(2)) {
            throw new BaseException("排列方向输入错误");
        }
        BizCourseChapter one = chapterMapper.selectOne(new QueryWrapper<BizCourseChapter>().lambda()
                .eq(BizCourseChapter::getBizCourseId, courseId)
                .eq(BizCourseChapter::getTitle, chapter.getTitle())
                .eq(BizCourseChapter::getIsDeleted, NEGATE));
        BizCourseChapter courseChapter;
        if (chapter.getId() == null) {
            if (one != null) {
                throw new BaseException("标题已存在");
            }
            courseChapter = new BizCourseChapter();
            courseChapter.setBizCourseId(courseId);
            courseChapter.setTitle(chapter.getTitle());
            courseChapter.setResourceType(chapter.getResourceType());
            courseChapter.setResourceUrl(chapter.getResourceUrl());
            courseChapter.setContent(chapter.getContent());
            courseChapter.setDuration(chapter.getDuration());
            courseChapter.setSort(chapter.getSort());
            courseChapter.setArrange(chapter.getArrange() == null ? 1 : chapter.getArrange());
            checkDisplay(courseChapter, chapter);
            chapterMapper.insert(courseChapter);
        } else {
            courseChapter = chapterMapper.selectById(chapter.getId());
            if (courseChapter == null || courseChapter.getIsDeleted().equals(SURE) || !courseChapter.getBizCourseId().equals(courseId)) {
                throw new BaseException("章节输入错误");
            } else if (one != null && !one.getId().equals(courseChapter.getId())) {
                throw new BaseException("标题已存在");
            }
            chapterMapper.update(null, new UpdateWrapper<BizCourseChapter>().lambda()
                    .eq(BizCourseChapter::getId, courseChapter.getId())
                    .set(BizCourseChapter::getBizCourseId, courseChapter.getBizCourseId())
                    .set(BizCourseChapter::getTitle, chapter.getTitle())
                    .set(BizCourseChapter::getResourceType, chapter.getResourceType())
                    .set(BizCourseChapter::getResourceUrl, chapter.getResourceUrl())
                    .set(BizCourseChapter::getContent, chapter.getContent())
                    .set(BizCourseChapter::getDuration, chapter.getDuration())
                    .set(BizCourseChapter::getSort, chapter.getSort())
                    .set(BizCourseChapter::getIsDisplay, courseChapter.getIsDisplay())
                    .set(BizCourseChapter::getDisplayAt, courseChapter.getDisplayAt())
                    .set(BizCourseChapter::getDisplayType, chapter.getDisplayType())
                    .set(BizCourseChapter::getIsDeleted, courseChapter.getIsDeleted())
                    .set(BizCourseChapter::getCreateAt, courseChapter.getCreateAt())
                    .set(chapter.getArrange() != null, BizCourseChapter::getArrange, chapter.getArrange())
                    .set(BizCourseChapter::getUpdateAt, courseChapter.getUpdateAt()));
        }
        formatSchedule(courseChapter.getId(), chapter.getDisplayType(), courseChapter.getIsDisplay(), chapter.getDisplayAt());
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void updateChapterStatus(Integer chapterId) {
        BizCourseChapter chapter = chapterMapper.selectById(chapterId);
        if (chapter == null || chapter.getIsDeleted().equals(SURE)) {
            throw new BaseException("章节输入错误");
        }
        chapterMapper.update(null, new UpdateWrapper<BizCourseChapter>().lambda()
                .eq(BizCourseChapter::getId, chapterId)
                .set(BizCourseChapter::getIsDisplay, chapter.getIsDisplay().equals(SURE) ? NEGATE : SURE)
                .set(BizCourseChapter::getDisplayAt, chapter.getIsDisplay().equals(SURE) ? null : LocalDateTime.now()));
    }

    @Override
    public CommonResult getChapterDetail(Integer chapterId) {
        BizCourseChapter chapter = chapterMapper.selectById(chapterId);
        if (chapter == null || chapter.getIsDeleted().equals(SURE)) {
            throw new BaseException("章节输入错误");
        }
        Chapter result = new Chapter();
        result.setId(chapterId);
        result.setResourceType(chapter.getResourceType());
        result.setResourceUrl(chapter.getResourceUrl());
        result.setTitle(chapter.getTitle());
        result.setContent(chapter.getContent());
        result.setSort(chapter.getSort());
        result.setDuration(chapter.getDuration());
        result.setDisplayType(chapter.getDisplayType());
        result.setDisplayAt(chapter.getDisplayAt());
        result.setArrange(chapter.getArrange());
        return CommonResult.success(result);
    }

    @Override
    public CommonResult getChapterList(PageParams query, Integer courseId) {
        PageHelper.startPage(query.getPage(), query.getSize());
        return CommonResult.restPage(chapterMapper.getChapterList(courseId));
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void deleteChapter(Integer chapterId) {
        BizCourseChapter chapter = chapterMapper.selectById(chapterId);
        if (chapter == null || chapter.getIsDeleted().equals(SURE)) {
            throw new BaseException("章节输入错误");
        }
        chapter.setIsDeleted(SURE);
        chapterMapper.updateById(chapter);
    }

    private BizCoreContent generateReading(Reading reading) {
        LocalDateTime now = LocalDateTime.now();
        BizCoreContent content = new BizCoreContent();
        content.setBizLabelId(reading.getLabelId());
        content.setTitle(reading.getTitle());
        content.setDescription(reading.getDescription());
        content.setImageV(reading.getImage());
        content.setAudioUrl(reading.getAudioUrl());
        content.setCreateAt(now);
        content.setProfile(reading.getProfile());
        content.setSort(reading.getSort());
        content.setIsCharge(NEGATE);
        content.setDuration(reading.getDuration());
        checkDisplay(content, reading);
        content.setContent(reading.getContent());
        content.setUpdateAt(now);
        return content;
    }

    private void checkDisplay(DisplayBase content, Daily daily) {
        LocalDateTime now = LocalDateTime.now();
        if (daily.getDisplayType().equals(DISPLAY_TYPE_NOT)) {
            content.setDisplayType(DISPLAY_TYPE_NOT);
            content.setIsDisplay(NEGATE);
            content.setDisplayAt(null);
        } else if (daily.getDisplayType().equals(DISPLAY_TYPE_NOW)) {
            content.setDisplayType(DISPLAY_TYPE_NOW);
            content.setIsDisplay(SURE);
            content.setDisplayAt(now);
        } else if (daily.getDisplayType().equals(DISPLAY_TYPE_TIME)) {
            content.setDisplayType(DISPLAY_TYPE_TIME);
            if (daily.getDisplayAt() == null) {
                throw new BaseException("上架时间不能为空");
            } else if (daily.getDisplayAt().isBefore(now)) {
                content.setDisplayAt(content.getDisplayAt() == null ? now : content.getDisplayAt());
                content.setIsDisplay(SURE);
            }
        } else {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
    }

    private BizCategory checkLabelAndGetCategory(String code, Integer labelId) {
        BizCategory category = categoryMapper.selectOne(new QueryWrapper<BizCategory>().lambda()
                .eq(BizCategory::getCode, code));
        if (labelId != null) {
            BizCategoryLabel label = labelMapper.selectById(labelId);
            if (label == null || !label.getBizCategoryId().equals(category.getId())) {
                throw new BaseException("标签输入错误");
            }
        }
        return category;
    }

    private BizCoreContent checkBizCoreContent(Integer contentId, BizCoreContent exitsContent) {
        BizCoreContent content = contentMapper.selectById(contentId);
        if (content == null || content.getIsDeleted().equals(SURE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        if (exitsContent != null && !exitsContent.getId().equals(contentId)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        return content;
    }

    private BizCoreContent generateCourse(Course params, BizCategory category) {
        if (params.getIsCharge().equals(SURE)) {
            if (params.getOriginalPrice() == null || params.getOriginalPrice().compareTo(BigDecimal.ZERO) <= 0
                    || params.getActualPrice() == null || params.getActualPrice().compareTo(BigDecimal.ZERO) <= 0) {
                throw new BaseException("价格输入错误");
            }
        } else if (!params.getIsCharge().equals(NEGATE)) {
            throw new BaseException("是否免费输入错误");
        }
        if (!params.getIsDisplay().equals(SURE) && !params.getIsDisplay().equals(NEGATE)) {
            throw new BaseException("上架状态选择错误");
        }
        BizCoreContent content = new BizCoreContent();
        content.setTitle(params.getTitle());
        content.setDescription(params.getDescription());
        content.setBizLabelId(params.getLabelId());
        content.setNum(params.getNum());
        content.setImageT(params.getImageT());
        content.setImageV(params.getImageV());
        content.setIsCharge(params.getIsCharge());
        content.setIsDisplay(params.getIsDisplay());
        content.setProfile(params.getProfile());
        content.setOriginalPrice(params.getOriginalPrice());
        content.setActualPrice(params.getActualPrice());
        content.setBizCategoryId(category.getId());
        content.setBizCategoryCode(category.getCode());
        content.setDisplayAt(LocalDateTime.now());
        content.setCreateAt(LocalDateTime.now());
        content.setUpdateAt(LocalDateTime.now());
        content.setDisplayAt(params.getIsDisplay().equals(SURE) ? LocalDateTime.now() : null);
        content.setSort(params.getSort());
        return content;
    }

    private void checkDisplay(BizCourseChapter courseChapter, Chapter chapter) {
        LocalDateTime now = LocalDateTime.now();
        if (chapter.getDisplayType().equals(DISPLAY_TYPE_NOW)) {
            courseChapter.setIsDisplay(SURE);
            courseChapter.setDisplayType(DISPLAY_TYPE_NOW);
            courseChapter.setDisplayAt(now);
        } else if (chapter.getDisplayType().equals(DISPLAY_TYPE_TIME)) {
            courseChapter.setDisplayType(DISPLAY_TYPE_TIME);
            if (chapter.getDisplayAt() == null) {
                throw new BaseException("上架时间不能为空");
            } else if (!chapter.getDisplayAt().isAfter(now)) {
                courseChapter.setIsDisplay(SURE);
                courseChapter.setDisplayAt(courseChapter.getDisplayAt() == null ? now : courseChapter.getDisplayAt());
            } else {
                courseChapter.setIsDisplay(NEGATE);
                courseChapter.setDisplayAt(null);
            }
        } else if (chapter.getDisplayType().equals(DISPLAY_TYPE_NOT)) {
            courseChapter.setDisplayType(DISPLAY_TYPE_NOT);
            courseChapter.setIsDisplay(NEGATE);
            courseChapter.setDisplayAt(null);
        } else {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
    }

    private void formatSchedule(Integer contentId, Integer displayType, Integer isDisplay, LocalDateTime startAt) {
        scheduleMapper.delete(new QueryWrapper<BizContentSchedule>().lambda()
                .eq(BizContentSchedule::getContentId, contentId)
                .eq(BizContentSchedule::getCode, CODE_COURSE));

        if (displayType.equals(DISPLAY_TYPE_TIME)) {
            BizContentSchedule schedule = new BizContentSchedule();
            schedule.setContentId(contentId);
            schedule.setCode(CODE_COURSE);
            schedule.setStartAt(startAt);
            schedule.setStatus(isDisplay);
            scheduleMapper.insert(schedule);
        }
    }
}
